#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
简化版问卷分析Web应用
"""

import os
import sys
import json
from datetime import datetime
from flask import Flask, render_template_string, request, jsonify, send_file
from flask_cors import CORS
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import matplotlib
matplotlib.use('Agg')  # 使用非交互式后端
import matplotlib.pyplot as plt
import seaborn as sns
import io
import base64
import platform

# 支持中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

# 清理字体缓存以确保字体设置生效
try:
    import matplotlib.font_manager as fm
    fm._rebuild()
except:
    pass

app = Flask(__name__)
CORS(app)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 16MB max file size

# 全局变量存储数据
current_data = None
analysis_results = {}

# HTML模板
INDEX_TEMPLATE = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>问卷数据分析系统</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: 'Microsoft YaHei', sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; }
        .container { max-width: 1200px; margin: 0 auto; padding: 20px; }
        .header { text-align: center; color: white; margin-bottom: 40px; }
        .header h1 { font-size: 2.5em; margin-bottom: 10px; }
        .card { background: white; border-radius: 15px; padding: 30px; margin-bottom: 30px; box-shadow: 0 10px 30px rgba(0,0,0,0.1); }
        .upload-area { border: 3px dashed #ddd; border-radius: 10px; padding: 40px; text-align: center; transition: all 0.3s; }
        .upload-area:hover { border-color: #667eea; background: #f8f9ff; }
        .upload-area.dragover { border-color: #667eea; background: #f0f4ff; }
        .btn { background: linear-gradient(45deg, #667eea, #764ba2); color: white; border: none; padding: 12px 30px; border-radius: 25px; cursor: pointer; font-size: 16px; transition: all 0.3s; }
        .btn:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0,0,0,0.2); }
        .btn:disabled { opacity: 0.6; cursor: not-allowed; }
        .results { margin-top: 30px; }
        .result-item { background: #f8f9fa; border-radius: 10px; padding: 20px; margin-bottom: 20px; }
        .chart-container { text-align: center; margin: 20px 0; }
        .chart-container img { max-width: 100%; border-radius: 10px; box-shadow: 0 5px 15px rgba(0,0,0,0.1); }
        .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin: 20px 0; }
        .stat-card { background: linear-gradient(45deg, #667eea, #764ba2); color: white; padding: 20px; border-radius: 10px; text-align: center; }
        .stat-number { font-size: 2em; font-weight: bold; }
        .stat-label { font-size: 0.9em; opacity: 0.9; }
        .loading { display: none; text-align: center; padding: 20px; }
        .spinner { border: 4px solid #f3f3f3; border-top: 4px solid #667eea; border-radius: 50%; width: 40px; height: 40px; animation: spin 1s linear infinite; margin: 0 auto; }
        @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
        .error { color: #e74c3c; background: #fdf2f2; padding: 15px; border-radius: 10px; margin: 10px 0; }
        .success { color: #27ae60; background: #f2fdf2; padding: 15px; border-radius: 10px; margin: 10px 0; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🔍 问卷数据分析系统</h1>
            <p>上传CSV文件，获得专业的数据分析报告</p>
        </div>
        
        <div class="card">
            <h2>📁 数据上传</h2>
            <div class="upload-area" id="uploadArea">
                <p>📤 拖拽CSV文件到此处，或点击选择文件</p>
                <input type="file" id="fileInput" accept=".csv" style="display: none;">
                <button class="btn" onclick="document.getElementById('fileInput').click()">选择文件</button>
            </div>
            <div id="fileInfo" style="margin-top: 15px;"></div>
        </div>
        
        <div class="card">
            <h2>⚙️ 分析选项</h2>
            <button class="btn" id="analyzeBtn" onclick="startAnalysis()" disabled>开始分析</button>
            <div class="loading" id="loading">
                <div class="spinner"></div>
                <p>正在分析数据，请稍候...</p>
            </div>
        </div>
        
        <div class="card" id="resultsCard" style="display: none;">
            <h2>📊 分析结果</h2>
            <div id="results"></div>
        </div>
    </div>
    
    <script>
        let selectedFile = null;
        
        // 文件上传处理
        const fileInput = document.getElementById('fileInput');
        const uploadArea = document.getElementById('uploadArea');
        const analyzeBtn = document.getElementById('analyzeBtn');
        
        fileInput.addEventListener('change', handleFileSelect);
        uploadArea.addEventListener('click', () => fileInput.click());
        uploadArea.addEventListener('dragover', handleDragOver);
        uploadArea.addEventListener('dragleave', handleDragLeave);
        uploadArea.addEventListener('drop', handleDrop);
        
        function handleFileSelect(e) {
            const file = e.target.files[0];
            if (file) processFile(file);
        }
        
        function handleDragOver(e) {
            e.preventDefault();
            uploadArea.classList.add('dragover');
        }
        
        function handleDragLeave(e) {
            e.preventDefault();
            uploadArea.classList.remove('dragover');
        }
        
        function handleDrop(e) {
            e.preventDefault();
            uploadArea.classList.remove('dragover');
            const file = e.dataTransfer.files[0];
            if (file) processFile(file);
        }
        
        function processFile(file) {
            if (!file.name.endsWith('.csv')) {
                showMessage('请选择CSV格式的文件', 'error');
                return;
            }
            
            selectedFile = file;
            document.getElementById('fileInfo').innerHTML = `
                <div class="success">
                    ✅ 已选择文件: ${file.name} (${(file.size/1024/1024).toFixed(2)} MB)
                </div>
            `;
            analyzeBtn.disabled = false;
        }
        
        function showMessage(message, type) {
            const div = document.createElement('div');
            div.className = type;
            div.textContent = message;
            document.getElementById('fileInfo').appendChild(div);
            setTimeout(() => div.remove(), 5000);
        }
        
        async function startAnalysis() {
            if (!selectedFile) return;
            
            const loading = document.getElementById('loading');
            const resultsCard = document.getElementById('resultsCard');
            
            loading.style.display = 'block';
            analyzeBtn.disabled = true;
            
            const formData = new FormData();
            formData.append('file', selectedFile);
            
            try {
                const response = await fetch('/analyze', {
                    method: 'POST',
                    body: formData
                });
                
                const result = await response.json();
                
                if (result.success) {
                    displayResults(result.data);
                    resultsCard.style.display = 'block';
                } else {
                    showMessage(result.error, 'error');
                }
            } catch (error) {
                showMessage('分析过程中发生错误: ' + error.message, 'error');
            } finally {
                loading.style.display = 'none';
                analyzeBtn.disabled = false;
            }
        }
        
        function displayResults(data) {
            const results = document.getElementById('results');
            results.innerHTML = `
                <div class="stats-grid">
                    <div class="stat-card">
                        <div class="stat-number">${data.basic_stats.total_rows}</div>
                        <div class="stat-label">总记录数</div>
                    </div>
                    <div class="stat-card">
                        <div class="stat-number">${data.basic_stats.total_columns}</div>
                        <div class="stat-label">字段数量</div>
                    </div>
                    <div class="stat-card">
                        <div class="stat-number">${data.basic_stats.missing_values}</div>
                        <div class="stat-label">缺失值</div>
                    </div>
                    <div class="stat-card">
                        <div class="stat-number">${data.basic_stats.duplicates}</div>
                        <div class="stat-label">重复记录</div>
                    </div>
                </div>
                
                <div class="result-item">
                    <h3>📈 数据分布图</h3>
                    <div class="chart-container">
                        <img src="data:image/png;base64,${data.charts.distribution}" alt="数据分布图">
                    </div>
                </div>
                
                <div class="result-item">
                    <h3>🔗 相关性热力图</h3>
                    <div class="chart-container">
                        <img src="data:image/png;base64,${data.charts.correlation}" alt="相关性热力图">
                    </div>
                </div>
                
                <div class="result-item">
                    <h3>🎯 聚类分析</h3>
                    <p><strong>聚类数量:</strong> ${data.clustering.n_clusters}</p>
                    <p><strong>轮廓系数:</strong> ${data.clustering.silhouette_score.toFixed(3)}</p>
                    <div class="chart-container">
                        <img src="data:image/png;base64,${data.charts.clustering}" alt="聚类分析图">
                    </div>
                </div>
                
                <div class="result-item">
                    <h3>💡 分析总结</h3>
                    <p>${data.summary}</p>
                </div>
            `;
        }
    </script>
</body>
</html>
"""

@app.route('/')
def index():
    return render_template_string(INDEX_TEMPLATE)

@app.route('/analyze', methods=['POST'])
def analyze():
    try:
        if 'file' not in request.files:
            return jsonify({'success': False, 'error': '没有上传文件'})
        
        file = request.files['file']
        if file.filename == '':
            return jsonify({'success': False, 'error': '没有选择文件'})
        
        # 读取CSV文件
        df = pd.read_csv(file)
        global current_data
        current_data = df
        
        # 基本统计信息
        basic_stats = {
            'total_rows': len(df),
            'total_columns': len(df.columns),
            'missing_values': df.isnull().sum().sum(),
            'duplicates': df.duplicated().sum()
        }
        
        # 数据清洗
        df_clean = df.dropna().drop_duplicates()
        
        # 选择数值列进行分析
        numeric_cols = df_clean.select_dtypes(include=[np.number]).columns
        if len(numeric_cols) == 0:
            return jsonify({'success': False, 'error': '数据中没有数值列可供分析'})
        
        df_numeric = df_clean[numeric_cols]
        
        # 生成图表
        charts = {}
        
        # 1. 数据分布图
        plt.figure(figsize=(12, 8))
        df_numeric.hist(bins=20, figsize=(12, 8))
        plt.suptitle('数据分布图', fontsize=16)
        plt.tight_layout()
        charts['distribution'] = get_plot_base64()
        
        # 2. 相关性热力图
        plt.figure(figsize=(10, 8))
        correlation_matrix = df_numeric.corr()
        sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0)
        plt.title('相关性热力图', fontsize=16)
        plt.tight_layout()
        charts['correlation'] = get_plot_base64()
        
        # 3. 聚类分析
        if len(df_numeric) > 10 and len(numeric_cols) >= 2:
            scaler = StandardScaler()
            X_scaled = scaler.fit_transform(df_numeric)
            
            # 确定最佳聚类数
            n_clusters = min(5, len(df_numeric) // 10, 8)
            if n_clusters < 2:
                n_clusters = 2
            
            kmeans = KMeans(n_clusters=n_clusters, random_state=42)
            clusters = kmeans.fit_predict(X_scaled)
            
            # 计算轮廓系数
            from sklearn.metrics import silhouette_score
            silhouette_avg = silhouette_score(X_scaled, clusters)
            
            # 绘制聚类图（使用前两个主成分）
            plt.figure(figsize=(10, 8))
            if len(numeric_cols) >= 2:
                plt.scatter(df_numeric.iloc[:, 0], df_numeric.iloc[:, 1], c=clusters, cmap='viridis')
                plt.xlabel(numeric_cols[0])
                plt.ylabel(numeric_cols[1])
            else:
                plt.scatter(range(len(clusters)), df_numeric.iloc[:, 0], c=clusters, cmap='viridis')
                plt.xlabel('样本索引')
                plt.ylabel(numeric_cols[0])
            
            plt.title(f'聚类分析结果 (K={n_clusters})', fontsize=16)
            plt.colorbar()
            plt.tight_layout()
            charts['clustering'] = get_plot_base64()
            
            clustering_info = {
                'n_clusters': n_clusters,
                'silhouette_score': silhouette_avg
            }
        else:
            clustering_info = {
                'n_clusters': 0,
                'silhouette_score': 0
            }
            charts['clustering'] = ''
        
        # 生成分析总结
        summary = generate_summary(basic_stats, correlation_matrix, clustering_info)
        
        result = {
            'success': True,
            'data': {
                'basic_stats': basic_stats,
                'charts': charts,
                'clustering': clustering_info,
                'summary': summary
            }
        }
        
        return jsonify(result)
        
    except Exception as e:
        return jsonify({'success': False, 'error': f'分析过程中发生错误: {str(e)}'})

def get_plot_base64():
    """将matplotlib图表转换为base64字符串"""
    buffer = io.BytesIO()
    plt.savefig(buffer, format='png', dpi=100, bbox_inches='tight')
    buffer.seek(0)
    plot_data = buffer.getvalue()
    buffer.close()
    plt.close()
    return base64.b64encode(plot_data).decode()

def generate_summary(basic_stats, correlation_matrix, clustering_info):
    """生成分析总结"""
    summary_parts = []
    
    # 数据质量评估
    missing_rate = basic_stats['missing_values'] / (basic_stats['total_rows'] * basic_stats['total_columns']) * 100
    duplicate_rate = basic_stats['duplicates'] / basic_stats['total_rows'] * 100
    
    if missing_rate < 5:
        summary_parts.append("数据质量良好，缺失值较少")
    elif missing_rate < 15:
        summary_parts.append("数据质量中等，存在一定缺失值")
    else:
        summary_parts.append("数据质量较差，缺失值较多，建议进一步清洗")
    
    if duplicate_rate > 10:
        summary_parts.append(f"发现{duplicate_rate:.1f}%的重复记录，建议去重处理")
    
    # 相关性分析
    if not correlation_matrix.empty:
        high_corr = (correlation_matrix.abs() > 0.7) & (correlation_matrix != 1.0)
        if high_corr.any().any():
            summary_parts.append("发现变量间存在强相关关系，可考虑降维处理")
        else:
            summary_parts.append("变量间相关性适中，特征相对独立")
    
    # 聚类分析
    if clustering_info['n_clusters'] > 0:
        if clustering_info['silhouette_score'] > 0.5:
            summary_parts.append(f"聚类效果良好，识别出{clustering_info['n_clusters']}个明显的用户群体")
        elif clustering_info['silhouette_score'] > 0.3:
            summary_parts.append(f"聚类效果中等，可识别出{clustering_info['n_clusters']}个用户群体")
        else:
            summary_parts.append("聚类效果一般，用户群体分化不明显")
    
    return "；".join(summary_parts) + "。"

if __name__ == '__main__':
    print("\n" + "="*60)
    print("🚀 问卷数据分析系统启动中...")
    print("📊 访问地址: http://127.0.0.1:5000")
    print("💡 支持CSV文件上传和实时分析")
    print("="*60 + "\n")
    
    app.run(host='127.0.0.1', port=5000, debug=False)